using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace ViNoToolkit{

	/// <summary>
	/// Vino Editor GUI Layout Utility class.
	/// </summary>
	static public class ViNoEditorGUILayout {

				#region PrivateMembers

		static private int currentActorID = 0;
		static private int currentSceneID = 0;
		static private bool eventsToggle = true;
		static private bool sceneToggle = true;
		static private bool actorToggle = true;
		static private bool dialogToggle = true;
		static private bool soundsToggle = true;
		
				#endregion

				#region Properties

		static int viewMode{ get; set; }

		/// <summary>
		/// Gets the content of the folder icon.
		/// </summary>
		/// <value>The content of the folder icon.</value>
		static private GUIContent folderIconContent{
			get{
				return new GUIContent( ViNoEditorResources.folderIcon );
			}
		}

		static private string[] m_ActorPopup;
		static public string[] actorPopup{
			get{			
				if( m_ActorPopup == null ){
						CollectActorNamesInActorLibrary();
				}			
				return m_ActorPopup;
			}
		}

		static private string[] m_ScenePopup;
		static public string[] scenePopup{
			get{			
				if( m_ScenePopup == null ){
						CollectSceneNamesInSceneLibrary();
				}			
				return m_ScenePopup;
			}
		}	

		static public string GetPopupActorName( ){
			return actorPopup [ currentActorID ];
		}

		static public string GetPopupSceneName( ){
			return scenePopup [ currentSceneID ];
		}

			#endregion

			#region PublicMethod
		/// <summary>
		/// Collects the actor names in actor library.
		/// Call this function , when an Actor is added in an ActorLibrary.
		/// </summary>
		static public void CollectActorNamesInActorLibrary(){
				SceneEvent se = GameObject.FindObjectOfType(typeof(SceneEvent)) as SceneEvent;
				if( se != null ){
						ActorLibrary actorLib = se.actorLib;
						List<string> actorNames = new List<string>();
						for(int i=0;i<actorLib.actorEntries.Length;i++){
								actorNames.Add( actorLib.actorEntries[ i ].actorName );
						}
						m_ActorPopup = actorNames.ToArray();
				}
		}

		/// <summary>
		/// Collects the scene names in scene library.
		/// Call this function , when Scene is added in a SceneLibrary.
		/// </summary>
		static public void CollectSceneNamesInSceneLibrary(){
				SceneEvent se = GameObject.FindObjectOfType(typeof(SceneEvent)) as SceneEvent;
				if( se != null ){					
						SceneLibrary sceneLib = se.sceneLib;
						List<string> sceneNames = new List<string>();				
						for(int i=0;i<sceneLib.sceneEntries.Length;i++){
								sceneNames.Add( sceneLib.sceneEntries[ i ].name );
						}
						m_ScenePopup = sceneNames.ToArray();
				}
		}
				#endregion

				#region DrawDialog

		/// <summary>
		/// Draws the XML import field.
		/// </summary>
		/// <param name="targetNode">Target node.</param>
		static public void DrawXMLImportField( DialogPartNode targetNode ){
			GUICommon.DrawLineSpace( 10f , 5f );
			GUILayout.BeginHorizontal();

			GUILayout.Space( 30f );

			targetNode.xmlData = EditorGUILayout.ObjectField( "XMLData" , targetNode.xmlData , typeof( TextAsset ) , false ) as TextAsset;

			EditorGUILayout.EndHorizontal();
			EditorGUILayout.BeginHorizontal();		

			if( GUILayout.Button ( "Export" ) ){
				string fileName =targetNode.name + ".xml";
				targetNode.SerializeXML( fileName );
				string path = ViNoGameSaveLoad.GetDataPath() + "/" + fileName;
				AssetDatabase.Refresh();

				Debug.Log( "Saved as Xml file path:" + path );
			}

			GUI.enabled = ( targetNode.xmlData != null ) ? true : false;

			if( GUILayout.Button ( "Import" ) ){
				if( EditorUtility.DisplayDialog( "Overwrite ?" , "Are you sure you really want to import?" , "Yes", "Cancel") ){
					targetNode.DeserializeXML( targetNode.xmlData.text );
					viewMode = 0;
				}
			}	

			GUI.enabled = true;				

			EditorGUILayout.EndHorizontal();		
		}

		/// <summary>
		/// Draws the dialog text box and name field.
		/// </summary>
		/// <param name="node">Node.</param>
		static public void DrawDialogTextBoxAndNameField( DialogPartNode node ){
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				if( GUILayout.Button( "Find" ) ){
						DialogPartNodeUtility.FindNameTextBox( node );
				}
				EditorGUILayout.LabelField( "NameTextBox" , GUILayout.Width( 100f) );
				node.m_NameTextBox = (ViNoTextBox)EditorGUILayout.ObjectField( node.m_NameTextBox , typeof( ViNoTextBox ) , true );
				if( node.m_NameTextBox != null ){
						node.m_NameHndName = node.m_NameTextBox.name;
				}
				EditorGUILayout.EndHorizontal();

				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				if( GUILayout.Button( "Find" ) ){
						DialogPartNodeUtility.FindDialogTextBox( node );
				}
				EditorGUILayout.LabelField( "TextBox", GUILayout.Width( 100f) );
				node.m_ViNoTextBox = (ViNoTextBox)EditorGUILayout.ObjectField( node.m_ViNoTextBox , typeof( ViNoTextBox ) , true );

				if( node.m_ViNoTextBox != null ){
						node.m_DialogHndName = node.m_ViNoTextBox.name;
				}

				EditorGUILayout.EndHorizontal();
		}


		/// <summary>
		/// Draw  + | - 
		/// at the bottom of the DialogPartNode.
		/// </summary>
		/// <param name="node">Node.</param>
		static public void DrawDialogListUtil( DialogPartNode node ){
				GUICommon.DrawLineSpace( 10f , 5f );

				ViNoEditorUtil.BeginGUIColor( Color.green , GUI.backgroundColor , GUI.contentColor );//Color.black , Color.white );

				GUILayout.BeginHorizontal();

				if( GUILayout.Button( "+" ) ){
						Undo.RegisterUndo ( node , node.name );

						int itemNum = node.GetMessageNum();
						node.AddItemAt( itemNum );
						node.ReAssignDialogIDsInThisObject();
				}

				if( GUILayout.Button( "-" ) ){
						Undo.RegisterUndo ( node , node.name );
						if( node.dlgDataList != null && node.dlgDataList.Count > 0 ){
								node.dlgDataList.RemoveAt( node.dlgDataList.Count - 1 );
						}
						node.ReAssignDialogIDsInThisObject();
				}

				GUILayout.EndHorizontal();		

				ViNoEditorUtil.EndGUIColor();
		}
										
		/// <summary>
		/// Draws the actor selector.
		/// </summary>
		/// <returns><c>true</c>, if actor selector was drawn, <c>false</c> otherwise.</returns>
		static public bool DrawActorSelector( ){
			bool isChanged = false;
			EditorGUI.BeginChangeCheck ();

			currentActorID = EditorGUILayout.Popup( currentActorID , actorPopup , GUILayout.Width( 100f ) );			

			if (EditorGUI.EndChangeCheck ()) {
					// Code to execute if GUI.changed
					// was set to true inside the block of code above.
					GUI.FocusControl( "" );
					isChanged = true;
			}				
			return isChanged;
		}

		/// <summary>
		/// Draws the scene selector.
		/// </summary>
		/// <returns><c>true</c>, if scene selector was drawn, <c>false</c> otherwise.</returns>
		static public bool DrawSceneSelector( ){
			bool isChanged = false;
			EditorGUI.BeginChangeCheck ();

			currentSceneID = EditorGUILayout.Popup( currentSceneID , scenePopup , GUILayout.Width( 150f ) );			

			if (EditorGUI.EndChangeCheck ()) {
					// Code to execute if GUI.changed
					// was set to true inside the block of code above.
					GUI.FocusControl( "" );
					isChanged = true;
			}				
			return isChanged;
		}
			
			static public void DrawCategory( string category , ref bool toggle ){
				if( EditorGUIUtility.isProSkin ){
						GUI.contentColor = Color.white;
						GUICommon.DrawLineSpace( 2f , 22f );

						EditorGUILayout.BeginHorizontal();
						GUILayout.Space( 15f );
								toggle = EditorGUILayout.Foldout( toggle , category );

						EditorGUILayout.EndHorizontal();
				}
				else{
						EditorGUILayout.BeginHorizontal();
						GUILayout.Space( 15f );
								toggle = EditorGUILayout.Foldout( toggle , category );

						EditorGUILayout.EndHorizontal();

						GUI.contentColor = Color.white;
						GUICommon.DrawLineSpace( 3f , 1f );
				}
		}

		/// <summary>
		/// Draws the event entry.
		/// </summary>
		/// <param name="label">Label.</param>
		/// <param name="node">Node.</param>
		/// <param name="data">Data.</param>
		/// <param name="eventData">Event data.</param>
		static public void DrawEventEntry( string label , DialogPartData data , ref DialogPartData.DialogEventData[] eventData ){
			EditorGUILayout.BeginHorizontal();
			GUILayout.Space( 30f );
			EditorGUILayout.LabelField( label );
			if( GUILayout.Button( "+" , GUILayout.Width( 80f ) ) ){
					GUI.FocusControl("");
					if( eventData == null || eventData.Length == 0 ){
							eventData = new DialogPartData.DialogEventData[ 1 ];
							eventData[ 0 ] = new DialogPartData.DialogEventData();
							eventData[ 0 ].targetObjectName = "EventManager";
					}
					else{
							ArrayUtility.Insert<DialogPartData.DialogEventData>( ref eventData , eventData.Length , new DialogPartData.DialogEventData() );
					}
			}

			if( GUILayout.Button( "-" , GUILayout.Width( 80f ) ) ){
					GUI.FocusControl("");
					ArrayUtility.RemoveAt<DialogPartData.DialogEventData>( ref eventData , eventData.Length - 1 );				
			}

			EditorGUILayout.EndHorizontal();

			if( eventData != null ){				
					for(int i=0;i<eventData.Length;i++){// DialogPartData.DialogEventData evt in eventData ) {
							EditorGUILayout.BeginHorizontal();
							GUILayout.Space( 45f );

							if( string.IsNullOrEmpty( eventData[ i ].targetObjectName ) ){
									eventData[ i ].targetObjectName = "EventManager";
							}
							//					eventData[ i ].targetObjectName = EditorGUILayout.TextField( "Target" , eventData[ i ].targetObjectName );

							eventData[ i ].methodName = EditorGUILayout.TextField( "SendMessage" , eventData[ i ].methodName );

							EditorGUILayout.EndHorizontal();
					}
			}

		}

		/// <summary>
		/// Draws the events category.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="data">Data.</param>
		static public void DrawEventsCategory( DialogPartData data ){
			if( EditorGUIUtility.isProSkin ){
					GUI.contentColor = Color.white;
					GUICommon.DrawLineSpace( 2f , 22f );

					EditorGUILayout.BeginHorizontal();
					GUILayout.Space( 15f );
					eventsToggle = EditorGUILayout.Foldout( eventsToggle , "Events" );

					EditorGUILayout.EndHorizontal();
			}
			else{
					EditorGUILayout.BeginHorizontal();
					GUILayout.Space( 15f );
					eventsToggle = EditorGUILayout.Foldout( eventsToggle , "Events" );

					EditorGUILayout.EndHorizontal();

					GUI.contentColor = Color.white;
					GUICommon.DrawLineSpace( 3f , 1f );
			}

			if( eventsToggle ){
					// Enter Events.
					DrawEventEntry( "Enter Events" , data , ref data.enterEventData );

					// Exit Events.
					DrawEventEntry( "Exit Events" , data , ref data.exitEventData );
			}
		}

		/// <summary>
		/// Draws the scene category.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawSceneCategory( DialogPartData unit ){
			if( EditorGUIUtility.isProSkin ){
				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 2f , 22f );

				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				sceneToggle = EditorGUILayout.Foldout( sceneToggle , "Scene" );

				if( GUILayout.Button( "Edit" , GUILayout.Width( 80f ) ) ){
						ViNoToolkit.SceneEvent se = GameObject.FindObjectOfType(typeof(ViNoToolkit.SceneEvent)) as ViNoToolkit.SceneEvent;
						EditorGUIUtility.PingObject( se.sceneLib.gameObject );
				}

				EditorGUILayout.EndHorizontal();
			}
			else{
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				sceneToggle = EditorGUILayout.Foldout( sceneToggle , "Scene" );

				if( GUILayout.Button( "Edit" , GUILayout.Width( 80f ) ) ){
						ViNoToolkit.SceneEvent se = GameObject.FindObjectOfType(typeof(ViNoToolkit.SceneEvent)) as ViNoToolkit.SceneEvent;
						EditorGUIUtility.PingObject( se.sceneLib.gameObject );
				}

				EditorGUILayout.EndHorizontal();

				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 3f , 1f );
			}

			if( sceneToggle ){
				NodeGUI.DrawLayoutSceneField( unit );
			}
		}
			
		/// <summary>
		/// Draws the actor category.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawActorCategory( DialogPartData unit ){		
			if( EditorGUIUtility.isProSkin ){
				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 2f , 22f );

				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				actorToggle = EditorGUILayout.Foldout( actorToggle , "Actors" );

				if( GUILayout.Button( "Edit" , GUILayout.Width( 80f ) ) ){
						ViNoToolkit.SceneEvent se = GameObject.FindObjectOfType(typeof(ViNoToolkit.SceneEvent)) as ViNoToolkit.SceneEvent;
						EditorGUIUtility.PingObject( se.actorLib.gameObject );
				}

				EditorGUILayout.EndHorizontal();
			}
			else{
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				actorToggle = EditorGUILayout.Foldout( actorToggle , "Actors" );

				if( GUILayout.Button( "Edit" , GUILayout.Width( 80f ) ) ){
						ViNoToolkit.SceneEvent se = GameObject.FindObjectOfType(typeof(ViNoToolkit.SceneEvent)) as ViNoToolkit.SceneEvent;
						EditorGUIUtility.PingObject( se.actorLib.gameObject );
				}

				EditorGUILayout.EndHorizontal();

				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 3f , 1f );
			}

			if( actorToggle ){			
				switch( unit.actionID ){
				case DialogPartNodeActionType.MoveActor:
				case DialogPartNodeActionType.EnterActor:
						NodeGUI.DrawLayoutEnterActorField( unit );				
						break;

				case DialogPartNodeActionType.Shake:
				case DialogPartNodeActionType.ExitActor:
						NodeGUI.DrawLayoutExitActorField( unit );				
						break;

				case DialogPartNodeActionType.ChangeState:
						NodeGUI.DrawLayoutChangeStateActorField( unit );
						break;
				}
			}
		}	
			
		/// <summary>
		/// Draws the sound category.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawSoundCategory( DialogPartData unit ){
			if( EditorGUIUtility.isProSkin ){
					GUI.contentColor = Color.white;
					GUICommon.DrawLineSpace( 2f , 22f );

					EditorGUILayout.BeginHorizontal();
					GUILayout.Space( 15f );
					soundsToggle = EditorGUILayout.Foldout( soundsToggle , "Sounds" );

					EditorGUILayout.EndHorizontal();
			}
			else{
					EditorGUILayout.BeginHorizontal();
					GUILayout.Space( 15f );
					soundsToggle = EditorGUILayout.Foldout( soundsToggle , "Sounds" );
					EditorGUILayout.EndHorizontal();

					GUI.contentColor = Color.white;
					GUICommon.DrawLineSpace( 3f , 1f );
			}

			if( soundsToggle ){
				float space = 30f;
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( space );
				unit.isBGM = EditorGUILayout.Toggle( unit.isBGM , GUILayout.Width( 10f ) );
				EditorGUILayout.LabelField( "Bgm" , GUILayout.Width( 35f ) );																		
				EditorGUILayout.LabelField( folderIconContent , GUILayout.Width( 16f ) );
				if( unit.isBGM ){
						DrawBGMPopupField( unit );
				}

				EditorGUILayout.EndHorizontal();					
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( space );
				unit.isSE = EditorGUILayout.Toggle( unit.isSE , GUILayout.Width( 10f ) );
				EditorGUILayout.LabelField( "SE" , GUILayout.Width(35f ) );																		
				EditorGUILayout.LabelField( folderIconContent , GUILayout.Width( 16f ) );
				if( unit.isSE ){
						DrawSEPopupField( unit );
				}

				EditorGUILayout.EndHorizontal();					
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( space );
				unit.isVoice = EditorGUILayout.Toggle( unit.isVoice , GUILayout.Width( 10f ) );
				EditorGUILayout.LabelField( "Voice" , GUILayout.Width(35f ) );																		
				EditorGUILayout.LabelField( folderIconContent , GUILayout.Width( 16f ) );
				if( unit.isVoice ){
						DrawVoicePopupField( unit );
				}

				EditorGUILayout.EndHorizontal();					
			}
		}

		/// <summary>
		/// Draws the dialog category.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawDialogCategory( DialogPartData unit ){	
			if( EditorGUIUtility.isProSkin ){
				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 2f , 22f );
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				dialogToggle = EditorGUILayout.Foldout( dialogToggle , "Dialog" );
				EditorGUILayout.EndHorizontal();
			}
			else{
				EditorGUILayout.BeginHorizontal();
				GUILayout.Space( 15f );
				dialogToggle = EditorGUILayout.Foldout( dialogToggle , "Dialog" );
				EditorGUILayout.EndHorizontal();

				GUI.contentColor = Color.white;
				GUICommon.DrawLineSpace( 3f , 1f );
			}
			if( dialogToggle ){
				// will be Drawn TextBox and NameTextBox field...
				//  .
				// ...

				NodeGUI.DrawLayoutNameField( unit );
				NodeGUI.DrawLayoutDialogTextField( unit );
			}
		}
		
		/// <summary>
		/// Draws the BGM popup field.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawBGMPopupField( DialogPartData unit  ){
			unit.bgmAudioKey =  EditorGUILayout.TextField( unit.bgmAudioKey , GUILayout.Width( 175f )  );
		}
			
		/// <summary>
		/// Draws the SE popup field.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawSEPopupField( DialogPartData unit ){
			EditorGUILayout.BeginHorizontal();
			unit.seAudioKey =  EditorGUILayout.TextField( unit.seAudioKey , GUILayout.Width( 175f )  );
				#if false
			if( GUILayout.Button( "Edit" ) ){
			string path = "Assets/Resources/" + unit.seAudioKey + ".wav";
			path = path.Replace( "\n" , "" );
			AudioClip audio = AssetDatabase.LoadAssetAtPath( path , typeof(AudioClip) ) as AudioClip;
			Debug.Log( "path : " + path );
			if( audio != null ){
			EditWindow.ShowWindow( audio );
			}
			else{
			Debug.LogWarning( "The resource not found." );
			}
			}
			#endif					
			EditorGUILayout.EndHorizontal();
		}
			
		/// <summary>
		/// Draws the voice popup field.
		/// </summary>
		/// <param name="node">Node.</param>
		/// <param name="unit">Unit.</param>
		static public void DrawVoicePopupField( DialogPartData unit  ){
			unit.voiceAudioKey =  EditorGUILayout.TextField( unit.voiceAudioKey , GUILayout.Width( 175f )  );
		}

			#endregion

	}

}
